#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/sysinfo.h>
#include <pthread.h>

#include "reader.h"
#include "psam_card.h"
#include "cpu_card.h"
#include "mifare_card.h"

int 	  DEBUG_APP_WALL	 =  __DEBUG_APP_O1__ ; // 默认打印信息


inline s32 reader_get_factor(reader_op *reader)
{
	s32 ret = 0;

	switch (reader->type) {
		case READER_CONTACTLESS_CPU:
			reader->deal_in_data.card_num[0] = 0x86;
			reader->deal_in_data.card_num[1] = 0x00;
			reader->deal_in_data.card_num[2] = 0x02;
			reader->deal_in_data.card_num[3] = 0x00;
			reader->deal_in_data.card_num[4] = 0x00;
			reader->deal_in_data.card_num[5] = 0x00;
			reader->deal_in_data.card_num[6] = 0x00;
			reader->deal_in_data.card_num[7] = 0x01;
			break;
			
		case READER_CONTACTLESS_M1:
			if (SECRTOR_KEY_FACTOR_ASN == reader->deal_in_data.factor_flag) {
			memset(reader->deal_in_data.m1.key_data, 0, 16);
			strncpy(reader->deal_in_data.m1.key_data, MIFARE_KA_NAME, \
				strlen(MIFARE_KA_NAME));
			ret = mifare_card_check_key(reader, S0B3, MIFARE_KA);
			if (ret) {
				printf("reader_get_factor: no.1 failed!!!\n");
				return RET_ERR;
			}

			ret = mifare_card_read_block(reader, S0B1);
			if (ret <= 0) {
				printf("reader_get_factor: no.2 failed!!!\n");
				return RET_ERR;
			}
			else {
				memcpy(reader->deal_in_data.card_num, reader->recv_data, 12);
			}

			reader->deal_in_data.card_num[0] = reader->deal_in_data.card_num[4];
			reader->deal_in_data.card_num[1] = reader->deal_in_data.card_num[5];
			reader->deal_in_data.card_num[2] = reader->deal_in_data.card_num[6];
			reader->deal_in_data.card_num[3] = reader->deal_in_data.card_num[7];
			reader->deal_in_data.card_num[4] = reader->deal_in_data.card_num[8];
			reader->deal_in_data.card_num[5] = reader->deal_in_data.card_num[9];
			reader->deal_in_data.card_num[6] = reader->deal_in_data.card_num[10];
			reader->deal_in_data.card_num[7] = reader->deal_in_data.card_num[11];
			}
			else if (SECRTOR_KEY_FACTOR_UID == reader->deal_in_data.factor_flag) {
				reader->deal_in_data.card_num[4] = reader->deal_in_data.card_num[0];
				reader->deal_in_data.card_num[5] = reader->deal_in_data.card_num[1];
				reader->deal_in_data.card_num[6] = reader->deal_in_data.card_num[2];
				reader->deal_in_data.card_num[7] = reader->deal_in_data.card_num[3];
			}
			else {
				printf("reader_get_factor: factor flag para error!!!\n");
				return RET_ERR;
			}
			break;

		default:
			printf("reader_get_factor: no.3 failed!!!\n");
			return RET_ERR;
	}

	return RET_OK;
}

static s32 reader_apdu_init_dev(reader_data *send, reader_data *recv)
{
	if (!send->data || !recv->data) {
		printf("psam_apdu_init_dev para error!!!\n");
		return RET_ERR;
	}
	
	/* 复位并初始化RC500 */
	memset(send->data, 0, READER_BUF_SIZ);
	send->type          = READER_SETTING;
	send->cmd.mf_comm   = RC500_INIT;
	send->pa1.mf_flag   = 0x13; 
	send->pa2.mf_sector = 0x00;
	send->len.mf_len    = 0x00;
	memset(recv->data, 0, READER_BUF_SIZ);

	return RET_OK;
}

static s32 reader_apdu_init_antenna(reader_data *send, reader_data *recv)
{
	if (!send->data || !recv->data) {
		printf("psam_apdu_init_antenna para error!!!\n");
		return RET_ERR;
	}

	/* 打开天线 */
	memset(send->data, 0, READER_BUF_SIZ);
	send->type          = READER_SETTING;
	send->cmd.mf_comm   = RC500_ANTENNA_CONTROL;
	send->pa1.mf_flag   = 0x01; 
	send->pa2.mf_sector = 0x00;
	send->len.mf_len    = 0x00;
	memset(recv->data, 0, READER_BUF_SIZ);

	return RET_OK;
}

static s32 reader_apdu_reset(reader_data *send, reader_data *recv)
{
	if (!send->data || !recv->data) {
		printf("psam_apdu_reset para error!!!\n");
		return RET_ERR;
	}

	/* 复位 */
	memset(send->data, 0, READER_BUF_SIZ);
	send->type          = READER_SETTING;
	send->cmd.mf_comm   = RC500_RST_CPU_CARD;
	send->pa1.mf_flag   = 0x00; 
	send->pa2.mf_sector = 0x00;
	send->len.mf_len    = 0x00;
	memset(recv->data, 0, READER_BUF_SIZ);

	return RET_OK;
}


static s32 reader_apdu_exit(reader_data *send, reader_data *recv)
{
	if (!send->data || !recv->data) {
		printf("psam_apdu_exit para error!!!\n");
		return RET_ERR;
	}

	// 退出卡
	memset(send->data, 0, READER_BUF_SIZ);
	send->type			= READER_SETTING;
	send->cmd.mf_comm	= RC500_DESELECT_CPU_CARD;
	send->pa1.mf_flag	= 0x00; 
	send->pa2.mf_sector = 0x00;
	send->len.mf_len	= 0x00;
	memset(recv->data, 0, READER_BUF_SIZ);

	return RET_OK;
}


/************************************
 * func: over reader and card communicate
 * para:
 *
 *  ret:
 *    0: ok
 *   -1: error
 ***********************************/
static s32 reader_apdu_over(reader_data *send, reader_data *recv)
{
	if (!send->data || !recv->data) {
		printf("psam_apdu_over para error!!!\n");
		return RET_ERR;
	}

	// 退出卡
	memset(send->data, 0, READER_BUF_SIZ);
	send->type			= READER_SETTING;
	send->cmd.mf_comm	= RC500_HALT_CARD;
	send->pa1.mf_flag	= 0x00; 
	send->pa2.mf_sector = 0x00;
	send->len.mf_len	= 0x00;
	memset(recv->data, 0, READER_BUF_SIZ);

	return RET_OK;
}



 inline static s32 reader_find(reader_op *reader)
{
	reader_data send, recv;
	int ret = 0;

	recv.data = reader->recv_data;
	
	/* 0x26只寻感应区内未进入休眠的卡 */
	/* 0x52寻感应区内所有符合14443A标准的卡 */
	send.type          = READER_SETTING;
	send.cmd.mf_comm   = RC500_FIND_CARD;
	send.pa1.mf_flag   = 0x26; 
	send.pa2.mf_sector = 0x00;
	send.len.mf_len    = 0x00;
	ret = reader_communication(reader->fd, &send, &recv);
	if (!ret) {
		/* 防冲突 */
		send.type          = READER_SETTING;
		send.cmd.mf_comm   = RC500_ANTI_COLLISION;
		send.pa1.mf_flag   = 0x00; 
		send.pa2.mf_sector = 0x00;
		send.len.mf_len    = 0x00;
		ret = reader_communication(reader->fd, &send, &recv);
		if (ret) {
			return RET_ERR;
		}
		else {
			// 这4位卡位为M1卡号 
			reader->deal_in_data.card_num[0] = recv.data[0];
			reader->deal_in_data.card_num[1] = recv.data[1];
			reader->deal_in_data.card_num[2] = recv.data[2];
			reader->deal_in_data.card_num[3] = recv.data[3];

			if (DEBUG_APP_WALL > __DEBUG_APP_O1__) {
				printf("reader find card num [%02x %02x %02x %02x]\n", \
					recv.data[0], recv.data[1], recv.data[2], recv.data[3]);
			}
		}
	}
	else {
		return RET_ERR;
	}

	/* 选择卡片 */
	send.type          = READER_SETTING;
	send.cmd.mf_comm   = RC500_SELECT_CARD;
	send.pa1.mf_flag   = 0x00; 
	send.pa2.mf_sector = 0x00;
	send.len.mf_len    = 0x04;
	send.data          = reader->deal_in_data.card_num;
	ret = reader_communication(reader->fd, &send, &recv);
	if (ret) {
		return RET_ERR;
	}

	return ret;
}


static void *reader_find_card_handle(void *arg)
{
	reader_data send, recv;
	reader_op* reader = (reader_op *)arg;
	struct sysinfo host_sysinfo;
	time_t reader_reset_time = 0;
	time_t cur_time = 0;
	int ret = 0;

	if (DEBUG_APP_WALL > __DEBUG_APP_O0__)
		printf("DEBUG_info: Reader find card start\n");

	send.data = reader->send_data;
	recv.data = reader->recv_data;

	// ret = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
	// ret = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);

	while (reader->run_flag) {
		usleep(1000*1000);
		sysinfo(&host_sysinfo);
		cur_time = host_sysinfo.uptime;
		if(cur_time >= reader_reset_time) {
			reader_apdu_reset(&send, &recv);
			reader_communication(reader->fd, &send, &recv);
			reader_reset_time = cur_time + 300;
		}

		if (reader->status == FIND_CARD_FAIL) {
				/* 寻卡成功card_id存有寻到卡片的物理ID */
				ret = reader_find(reader);
				if (!ret) {
					reader_apdu_reset(&send, &recv);
					ret = reader_communication(reader->fd, &send, &recv);
					if (!ret) {
						if (DEBUG_APP_WALL > __DEBUG_APP_O0__) {
							printf("CPU card connecting...\n");
						}
						
						reader->type    = READER_CONTACTLESS_CPU;
						reader->status  = FIND_CARD_SUCC;
						reader->deal_op = cpu_card_deal;
						reader->load_op = cpu_card_load;
						continue;
					}
				}
				
				/* 寻卡成功card_id存有寻到卡片的物理ID */
				ret = reader_find(reader);
				if (!ret) {
					if (DEBUG_APP_WALL > __DEBUG_APP_O0__) {
						printf("M1 card connecting...\n");
					}

					reader->type    = READER_CONTACTLESS_M1;
					reader->deal_op = mifare_card_deal;
					reader->status  = FIND_CARD_SUCC;
					continue;
				}
			}
		}

	pthread_exit(0);
}


/************************************
 * func: open reader
 * para:
 *
 *  ret:
 *   -1: error
 ***********************************/
static s32 reader_open(const s8 *path)
{  
	s32 fd = 0;

	fd = open(path, O_RDWR);
	if (-1 == fd) {
		printf("reader open fail\n");
		return RET_ERR;
	}

	return fd;
}

static s32 reader_close(s32 fd)
{
	if (fd > 0) {
		close(fd);
		fd = 0;
		
		return RET_OK;
	}
	else {
		printf("read_close pare error!!!\n");
		return RET_ERR;
	}
}



/************************************
 * func: init reader
 * para:
 *
 *  ret:
 *   
 ***********************************/
reader_op* reader_attr_init(s8 *dev_name)
{
	reader_data send, recv;
	u8 pin[16];
	u8 num[3];
	u8 i, j;
	int ret;
	reader_op *reader = NULL;

	if (!dev_name) {
		printf("reader_attr_init para error!!!\n");
		return NULL;
	}

	reader = (reader_op *)malloc(sizeof(reader_op));
	if (!reader) {
		printf("malloc reader_op failed!!!\n");
		return NULL;
	}

		// 初始化数据
	memset(reader, 0, sizeof(reader_op));
	reader->deal_op    = NULL;
	reader->load_op    = NULL;
	reader->type       = READER_CONTACTLESS_M1;
	reader->status     = FIND_CARD_FAIL;
	reader->run_flag   = 1;
	reader->deal_in_data.m1.endian = APP_BIG_ENDIAN;
	reader->deal_in_data.factor_flag = SECRTOR_KEY_FACTOR_ASN;
	strncpy(pin, READER_PIN, strlen(READER_PIN));
	for (i=0,j=0; i<3; i++) {
		num[i] = pin[j++] - '0';
		num[i+1] = pin[j++] - '0';
		reader->deal_in_data.pin[i] = (num[i] * 16) + num[i+1];
	}

	ret = reader_open(dev_name);
	if (ret > 0) {
		reader->fd = ret;
	}
	else {
		return NULL;
	}


	send.data = reader->send_data;
	recv.data = reader->recv_data;
	reader_apdu_init_dev(&send, &recv);
	ret = reader_communication(reader->fd, &send, &recv);
	if (ret) {
		return NULL;
	}

	reader_apdu_init_antenna(&send, &recv);
	ret = reader_communication(reader->fd, &send, &recv);
	if (ret) {
		return NULL;
	}


	if (DEBUG_APP_WALL > __DEBUG_APP_O0__) {
		printf("DEBUG_info: reader init done\n");
	}

	return reader;

}



s32 reader_search_start(reader_op* reader)
{
	s32 ret;
	pthread_t  pid;
	pthread_attr_t attr;

	if (!reader || reader->fd <= 0) {
		printf("reader_start pare error!!!\n");
	}
	
	ret = psam_card_init(reader);
	if (ret) {
		return RET_ERR;
	}
	ret += pthread_attr_init(&attr); // 初始化线程
	ret += pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); // 设置线程为分离属性
	// ret = pthread_attr_setscope(&attr, PTHREAD_SCOPE_PROCESS); // 设置线程为非绑定属性
	ret += pthread_create(&pid, &attr, reader_find_card_handle, (void *)reader);
	if (ret) {
		printf("pthread_create failed!!!\n");
		return RET_ERR;
	}
	// ret = pthread_attr_destroy(&attr); // 回收资源

	return RET_OK;
}


/************************************
 * func: reader and card communicate
 * para:
 *
 *  ret:
 *    0: ok 
 *   -1: error
 *   -2: send->type is fail
 *   -3: reader write error
 *   -4: reader read error
 ***********************************/
inline s32 reader_communication(const s32 fd, reader_data *send, reader_data *recv)
{
	s32 i = 0;
	s32 len = 0;
	s32 ret = 0;

	if (fd <= 0 || !send || !recv \
		|| !send->data || !recv->data) {
		printf("reader_communication para error!!!\n");
		recv->sw1 = 0x65;
		recv->sw2 = 0x00;
		return RET_ERR;
	}


	// 数据格式
	switch (send->type) {
		case READER_CONTACTLESS_M1:
		case READER_SETTING:
			recv->data[len++] = send->cmd.mf_comm;
			recv->data[len++] = send->pa1.mf_flag;
			recv->data[len++] = send->pa2.mf_sector;
			recv->data[len++] = send->len.mf_len;
			
			if ((send->len.mf_len) && (!send->data)) {
				printf("send->data pointer is NULL\n");
				recv->sw1 = 0x65;
				recv->sw2 = 0x00;
				return RET_ERR;
			}
			
			for (i=0; i<send->len.mf_len; i++) {
				recv->data[len++] = send->data[i];
			}
			recv->data[len++] = 0;
			break;
			
		case READER_CONTACT_SAM1:
		case READER_CONTACTLESS_24G:
		case READER_CONTACTLESS_CPU:
			recv->data[len++] = send->type;
			recv->data[len++] = 0;
			recv->data[len++] = 0;
			recv->data[len++] = 0;
			recv->data[len++] = send->cla;	
			recv->data[len++] = send->cmd.ins;	
			recv->data[len++] = send->pa1.p1;	
			recv->data[len++] = send->pa2.p2;
			
			if (send->len.lc == 0) {	
				recv->data[len++] = send->le;
			}
			else {
				if ((send->len.lc) && (!send->data)) {
					printf("send->DATA pointer is NULL\n");
					recv->sw1 = 0x65;
					recv->sw2 = 0x00;
					return RET_ERR;
				}
				recv->data[len++] = send->len.lc;
				
				for (i=0; i<send->len.lc; i++) {
					recv->data[len++] = send->data[i];
				}

				if (send->le) {
					recv->data[len++] = send->le;
				}
				
			}
			recv->data[3]  = len - 4;
			break;

		default:
			recv->sw1 = 0x65;
			recv->sw2 = 0x00;
			return RET_ERR_TYPE;

	}

	
	// 工程调试信息
	if (DEBUG_APP_WALL > __DEBUG_APP_O2__) {
		switch (send->type) {
			case READER_SETTING:
			case READER_CONTACTLESS_M1:
				if (send->type != READER_SETTING) {
					printf("reader send to [M1] %02d data:\n", len);
					for (i=0; i<len; i++) {
						printf("%02X ", recv->data[i]);
					}
					printf("\n");
				}
				break;

			case READER_CONTACT_SAM1:
			case READER_CONTACTLESS_24G:
			case READER_CONTACTLESS_CPU:
				if (send->type == READER_CONTACTLESS_24G) {
					printf("reader send to [2.4G] %02d data:\n", len);
				}
				else if (send->type == READER_CONTACTLESS_CPU) {
					printf("reader send to [cpu] %02d data:\n", len);
				}
				else if (send->type == READER_CONTACT_SAM1) {
					printf("reader send to [sam] %02d data:\n", len);
				}
				
				for (i=0; i<len; i++) {
					printf("%02X ", recv->data[i]);
				}
				printf("\n");
				break;

				
		}

	}
 
	switch (send->type) {
		case READER_CONTACTLESS_24G:
			break;

		case READER_SETTING:
		case READER_CONTACT_SAM1:
		case READER_CONTACTLESS_CPU:
		case READER_CONTACTLESS_M1:
			ret = write(fd, recv->data, len);
			if (ret < 0) {
                if (send->type != READER_SETTING) {
				    printf("reader write error\n");
                }
				recv->sw1 = 0x65;
				recv->sw2 = 0x00;
				return RET_ERR_WRITE;
			}

			ret = read(fd, recv->data, READER_BUF_SIZ);
			if (ret < 0) {
                if (send->type != READER_SETTING) {
				    printf("reader read error\n");
                }
				recv->sw1 = 0x65;
				recv->sw2 = 0x00;
				return RET_ERR_READ;
			}
			break;

		default:
			recv->sw1 = 0x65;
			recv->sw2 = 0x00;
			return RET_ERR_TYPE;
	}

	// 工程调试信息
	if (DEBUG_APP_WALL > __DEBUG_APP_O2__) {
		if (send->type != READER_SETTING) {
			printf("reader recv %d data:\n", ret);
			for (i=0; i<ret; i++) {
				printf("%02X ", recv->data[i]);
			}
			printf("\n");
		}
	}

	len = 0;
	recv->cmd.mf_comm   = recv->data[len++];
	recv->pa1.mf_flag   = recv->data[len++];
	recv->pa2.mf_sector = recv->data[len++];
	recv->len.mf_len    = recv->data[len++];

	if (recv->data) {
		for(i=0; i<recv->len.mf_len; i++) {
			recv->data[i] = recv->data[len++];
		}
		recv->data[i] = recv->data[len]; 

		switch (send->type) {
			case READER_CONTACTLESS_24G:
			case READER_CONTACTLESS_CPU:
			case READER_CONTACT_SAM1:
				if (recv->len.lc > 1) {
					recv->sw1 = recv->data[recv->len.lc-2];
					recv->sw2 = recv->data[recv->len.lc-1];
				} 
				else {
					recv->sw1 = 0x65;
					recv->sw2 = 0x00;
				}
				break;
				
			default:
				recv->sw1 = 0x90;
				recv->sw2 = 0x00;
				break;
		}
	}

	return RET_OK;  
}


s32 reader_attr_destroy(reader_op *reader)
{
	if (!reader || !reader->recv_data || !reader->send_data) {
		printf("reader_attr_destroy pare error!!!\n");
		return RET_ERR;
	}
	
	reader_close(reader->fd);
	reader->run_flag = 0;
	free(reader);

	return RET_OK;
}


